/**
 * 开源版本请务必保留此注释头信息，若删除捷码开源〔GEMOS〕官方保留所有法律责任追究！
 * 本软件受国家版权局知识产权以及国家计算机软件著作权保护（登记号：2018SR503328）
 * 不得恶意分享产品源代码、二次转售等，违者必究。
 * Copyright (c) 2020 gemframework all rights reserved.
 * http://www.gemframework.com
 * 版权所有，侵权必究！
 */
package com.gemframework.service.impl;

import com.gemframework.common.exception.GemException;
import com.gemframework.common.utils.GemRedisUtils;
import com.gemframework.common.utils.GemUUIDUtils;
import com.gemframework.model.common.ApiToken;
import com.gemframework.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.gemframework.model.enums.ExceptionCode.*;

@Slf4j
@Service
public class TokenServiceImpl implements TokenService {

    @Autowired
    GemRedisUtils gemRedisUtils;

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // AccessToken有效期限 单位秒
    public static final int ACCESSTOKEN_EXPIRE = 7200;

    // RefreshToken有效期限 单位小时
    private static final int REFRESHTOKEN_EXPIRE = 7;


    public static String getTokenKeyByMemberId(Long memberId){
        return  "accessToken_memberId:"+memberId;
    }
    public static String getTokenKey(String token){
        return "accessToken:"+token;
    }

    /**
     * @Title: refreshToken
     * @Description: 刷新token
     * @param memberId
     * @param refreshToken
     */
    public ApiToken refreshToken(Long memberId, String refreshToken){
        ApiToken token = (ApiToken) gemRedisUtils.get(getTokenKeyByMemberId(memberId));
        Date now = new Date();
        if(token==null){
            throw new GemException(NO_TOKEN);
        }
        if(now.after(token.getRefreshTokenExpireTime())){
            throw new GemException(REFRESH_TOKEN_INVALID);
        }
        if(!refreshToken.equals(token.getRefreshToken())){
            throw new GemException(REFRESH_TOKEN_ERROR);
        }
        token = creatToken(memberId);
        return token;
    }

    /**
     * @Title: creatToken
     * @Description: 创建token
     * @param memberId
     */
    public ApiToken creatToken(Long memberId){
        ApiToken token = new ApiToken();
        token.setMemberId(memberId);
        token.setAccessToken(GemUUIDUtils.uuid2());
        token.setRefreshToken(GemUUIDUtils.uuid2());
        Date now = new Date();
        try {
            now = sdf.parse(sdf.format(now));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar oneHour = Calendar.getInstance();
        oneHour.setTime(now);
        oneHour.add(Calendar.SECOND, ACCESSTOKEN_EXPIRE);
        token.setAccessTokenExpireTime(oneHour.getTime());
        Calendar oneWeek = Calendar.getInstance();
        oneWeek.setTime(now);
        oneWeek.add(Calendar.DAY_OF_YEAR, REFRESHTOKEN_EXPIRE);
        token.setRefreshTokenExpireTime(oneWeek.getTime());
        token.setUpdateTime(now);
        gemRedisUtils.setEx(getTokenKeyByMemberId(memberId),token,ACCESSTOKEN_EXPIRE, TimeUnit.SECONDS);
        //设置会员ID redis key=accessToken:xxxx
        gemRedisUtils.setEx(getTokenKey(token.getAccessToken()),memberId,ACCESSTOKEN_EXPIRE, TimeUnit.SECONDS);
        return token;
    }
}